package peace.gui.controls.navigation
{
import flash.display.Sprite;
import flash.events.MouseEvent;

import peace.gui.controls.ExistenceEvent;
import peace.gui.controls.RubberSprite;
import peace.gui.controls.SelectEvent;
import peace.gui.controls.buttons.PushButton;
import peace.gui.layout.Align;
import peace.gui.layout.Container;
import peace.gui.layout.RowLayout;
import peace.gui.layout.Valign;

/**
* выбор таба по метке 
*/
[Event(name="change", type="peace.gui.controls.SelectEvent")]
/**
* закрытие таба
*/
[Event(name="close", type="peace.gui.controls.ExistenceEvent")]
/**
* панель кнопок с возможностью закрытия (close-button)
*/
public class Tabbar extends RubberSprite
{
	/**
	 * 
	 */
	protected static const DEFAULT_WIDTH:Number = int.MAX_VALUE;
	
	/**
	 * храним массив меток
	 */
	public var labels:Array = [];
	/**
	 * хеш табов по метке 
	 */	
	protected var tabs:Object = {};
	/**
	 * 
	 */
	protected var selectedTab:Tab;
	/**
	 * 
	 */	
	protected var closable:Boolean;
	/**
	 * 
	 */
	protected var tabButtonSkin:Class;
	/**
	 * 
	 */
	protected var closeButtonSkin:Class;
	/**
	 * 
	 */	
	protected var container:Container = new Container(new RowLayout(null, 0, Align.LEFT, Valign.BOTTOM))
	/**
	 * 
	 * @param labels
	 * @param tabButtonSkin
	 * @param closeButtonSkin
	 * 
	 */	
	public function Tabbar (labels:Array = null, closable:Boolean = false, tabButtonSkin:Class = null, closeButtonSkin:Class = null)
	{
		super();
		this.tabButtonSkin = tabButtonSkin || PushButton;
		this.closeButtonSkin = closeButtonSkin || DefaultCloseButtonSkin;
		this.closable = closable;
		
		size.width = DEFAULT_WIDTH;
		
		addChild(container);
		
		if (labels)
		{
			// делаем копию иначе рекурсия
			this.labels = labels.slice(); 
			
			var l:String;
			for each (l in labels)
			{
				freezeArrange = true;
				add (l);
			}
			freezeArrange = false;
			arrange();
		}
	}
	/**
	 * 
	 * @param label
	 * @param hasClose
	 * 
	 */	
	public function add (label:String):void
	{
		var t:Tab = createTab(label);
		
		tabs[label] = t;
		container.add(t);
		labels.push(label);

		t.button.addEventListener(MouseEvent.CLICK, onTabClick, false,0,true);
		if (closable) t.close.addEventListener(MouseEvent.CLICK, onTabClose, false,0,true);
		
		arrange();
	}
	/**
	 * 
	 * @param label
	 * 
	 */	
	public function remove (label:String):void
	{
		var t:Tab = Tab (tabs[label]);
		if (t)
		{
			delete tabs[label];
			container.remove(t);
			labels.splice (labels.indexOf(label), 1);
			
			t.button.removeEventListener(MouseEvent.CLICK, onTabClick);
			if (closable) t.close.removeEventListener(MouseEvent.CLICK, onTabClose);

			arrange();
			
			dispatchEvent (new ExistenceEvent(ExistenceEvent.CLOSE, label));
			
			if (t == selectedTab && container.children.length > 0)
			{
				t = Tab (container.children[0]);
				select (t.label);
			}
		}
	}
	/**
	 * 
	 * @param label
	 * 
	 */	
	public function select (label:String):void
	{
		var t:Tab = Tab (tabs[label]);
		if (t && t != selectedTab)
		{
			if (selectedTab) selectedTab.button.selected = false;
			t.button.selected = true;
			
			selectedTab = t;
			container.setChildIndex (t, container.numChildren-1);
			
			dispatchEvent (new SelectEvent(SelectEvent.CHANGE, label));
		}
		else if (t && t == selectedTab)
		{
			// не снимаем выделение
			t.button.selected = true;
		}
	}
	/**
	 * virtual <br>
	 * 
	 * Возможность добавить табу ништяков
	 * 
	 * @param label String
	 *  
	 * @return Tab
	 * 
	 */
	protected function createTab (label:String):Tab
	{
		var tabbutton:PushButton = new tabButtonSkin();
		tabbutton.value = label;
		return new Tab (tabbutton, closable ? new closeButtonSkin : null);
	}
	/**
	 * 
	 * @param v
	 * 
	 */	
	override public function set value(v:*):void
	{
		select (v);
	}
	/**
	 * 
	 * @return 
	 * 
	 */	
	override public function get value():*
	{
		return selectedTab ? selectedTab.label : null; 
	}
	/**
	 * 
	 * @param index
	 * 
	 */
	public function set selectedIndex (index:int):void
	{
		select (labels[index]);
	}
	/**
	 * 
	 * @return 
	 * 
	 */
	public function get selectedIndex ():int
	{
		return selectedTab ? labels.indexOf(selectedTab.label) : -1;
	}
	
	/**
	 * 
	 * 
	 */	
	override public function arrange():void
	{
		if (freezeArrange) return;
		
		container.userWidth = size.width;	
		container.userHeight = size.height;
		
		var w:Number = 0;
		var t:Tab;
		for each (t in container.children)
		{
			w += t.width;
		}
		
		container.layout.hSpacing = Math.min ((size.width - w)/(container.children.length-1), 0);
		
		container.arrange();
	}
	/**
	 * Переопределяем, ибо размер по умолчанию великоват...
	 * 
	 * @return 
	 * 
	 */	
	override public function get width():Number
	{
		return container.layout.width;
	}
	/**
	 * 
	 * @return 
	 * 
	 */	
	override public function get height():Number
	{
		return container.length > 0 ? Tab(container.children[0]).height : 0;
	}
	/**
	 * 
	 * @param e
	 * 
	 */	
	private function onTabClick (e:MouseEvent):void
	{
		var t:Tab = Tab (e.currentTarget.parent);
		select (t.label);
	}
	/**
	 * 
	 * @param e
	 * 
	 */	
	private function onTabClose (e:MouseEvent):void
	{
		var t:Tab = Tab (e.currentTarget.parent);
		remove (t.label);
	}
	
}
}

import flash.display.Sprite;
import peace.gui.controls.buttons.PushButton;
import flash.display.Shape;

internal class Tab extends Sprite
{
	public var button:PushButton;
	public var close:PushButton;
	
	private var closeSpacing:Number = 2;
	
	public function Tab (button:PushButton, close:PushButton)
	{
		this.button = button;
		this.close = close;
		
		init();
	}
	
	protected function init ():void
	{
		var w:Number = button.getIcon().width;

		addChild(button);
		
		if (close)
		{
			// сдвигаем метку, чтобы влезла close
			button.width = w + 15;
			button.getIcon().x -= 3;

			addChild(close);
			close.x = button.width - close.width - closeSpacing;
			close.y = closeSpacing;
		}
		else
		{
			// тюнинг ширины кнопки
			button.width = w + 12;
		}
	}

	public function get label ():String
	{
		return button.value;
	}
	
	override public function get width():Number
	{
		return button.width;
	}
	
	override public function get height():Number
	{
		return button.height;
	}
	
}

internal class DefaultCloseButtonSkin extends PushButton
{
	public function DefaultCloseButtonSkin ()
	{
		var cross:Shape = new Shape();
		with (cross.graphics)
		{
			lineStyle(0, 0, 1);
			beginFill(0,0);
			drawRect(0,0,8,8);
			lineTo(8,8);
			moveTo(8,0);
			lineTo(0,8);
			endFill();
		}
		super(cross);
	}
}


